package org.kolonitsky.alexey.utils
{
    /**
     *  Common string methods not included to String class.
     */ 
    public class StringUtils
    {
        /**
         *  Get plural form of numeral. 
         *  
         *  @param num is a numeral 
         *  @param one
         *  @param two
         *  @param five
         */
        public static function getPluralNoun(num:int, one:String, two:String, five:String):String
        {
            num = Math.abs(num);
            num %= 100;
            
            if (num >= 5 && num <= 20)
                return five;
            
            num %= 10;
            if (num == 1) 
                return one;
            
            if (num >= 2 && num <= 4)
                return two;
            
            return five;
        }
        
        /**
         *  Get plural form of adjective
         *  
         *  @param num is a numeral 
         *  @param one
         *  @param two
         */
        public static function getPluralAdjactive(num:int, one:String, two:String):String
        {
            num %= 100;
            if (num == 11) 
                return two;
            
            num %= 10;
            if (num == 1) 
                return one;
            
            return two;
        }
        
        /**
         *  
         */
        public static function capitalizeWordFirstLetter(word:String):String
        {
            switch (word) 
            { 
                case "and": 
                case "the": 
                case "in": 
                case "an": 
                case "or": 
                case "at": 
                case "of": 
                case "a": 
                    // Don't do anything to these words. 
                    break; 
                
                default: 
                    // For any other word, capitalize the first character. 
                    var firstLetter:String = word.substr(0, 1); 
                    firstLetter = firstLetter.toUpperCase(); 
                    var otherLetters:String = word.substring(1); 
                    word = firstLetter + otherLetters; 
            } 
            return word;
        }
        
        /**
         *  
         */ 
        public static function capitalizeFirsLetter(string:String):String
        {
            var array:Array = string.split(" ");
            var result:String = "";
            for each (var oneWord:String in array)
                result += capitalizeWordFirstLetter(oneWord);
            return result;
        }
		
		/**
		 *  TODO: Add parsing of GET parameters
		 */
		public static function validateURL(url:String):Object
		{
			var result:Object = null;
			var address:Array = /((?P<protocol>http):\/\/)*(?P<filename>[a-z0-9\-._]+(\/|$))*/i.exec(url);
			if (address)
			{
				result = {};
				var startInd:int = 0;
				if ("protocol" in address) 
				{
					result.protocol = address.protocol;
					startInd = String(result.protocol).length + 3;
				}
				
				var endInd:int = 0;
				if ("filename" in address)
				{
					result.filename = address.filename;
					endInd = url.indexOf(result.filename, startInd);
				}
				
				url = url.substring(startInd, endInd);
				var domainArray:Array = /(?P<domain>([a-z0-9\-]+.)(?P<zone>[a-z]{2,3}))(:?\/|$)/i.exec(url);
				if (domainArray)
				{
					if ("domain" in domainArray)
						result.domain = domainArray.domain;
					
					if ("zone" in domainArray)
						result.zone = domainArray.zone;
				}
			}
			
			return result;
		}
        
        
		public static var NEWLINE_TOKENS : Array = new Array (
			'\n',
			'\r'
		);
		
		public static var WHITESPACE_TOKENS : Array = new Array (
			' ',
			'\t'
		);
        
        public static function parsGetParams(string:String):Object
        {
            var result:Object = {};

            if (string == null || string.length == 0)
                return result;
            
            var paramsArray:Array = string.split("&");
            var pairArray:Array;
            for each (var pair:String in paramsArray)
            {
                pairArray = pair.split("=");
                if (pairArray && pairArray.length == 2)
                    result[pairArray[0]] = pairArray[1];
            }
            return result;
        }
		
		public static function count ( haystack : String, needle : String, offset : Number = 0, length : Number = 0 ) : Number
		{
			if ( length === 0 )
				 length = haystack.length
			var result : Number = 0;
			haystack = haystack.slice( offset, length );
			while ( haystack.length > 0 && haystack.indexOf( needle ) != -1 )
			{
				haystack = haystack.slice( ( haystack.indexOf( needle ) + needle.length ) );
				result++;
			}
			return result;
		}
		

		public static function trim (str:String, charList:Array=null):String
		{
			var list : Array;
			if ( charList )
				list = charList;
			else
				list = WHITESPACE_TOKENS.concat( NEWLINE_TOKENS );
			str = trimLeft( str, list );
			str = trimRight( str, list );
			return str;
		}
		
		public static function trimLeft ( str : String, charList : Array = null ) : String
		{
			var list:Array;
			if ( charList )
				 list = charList;
			else
				 list = WHITESPACE_TOKENS.concat( NEWLINE_TOKENS );
			
			while ( list.toString().indexOf ( str.substr ( 0, 1 ) ) > -1 && str.length > 0 )
					str = str.substr ( 1 );
			return str;
		}
		
		public static function trimRight ( str:String, charList : Array = null ) : String
		{
			var list : Array;
			if ( charList )
				 list = charList;
			else
				 list = WHITESPACE_TOKENS.concat( NEWLINE_TOKENS );
			
			while ( list.toString().indexOf ( str.substr ( str.length - 1 ) ) > -1 && str.length > 0)
					str = str.substr ( 0, str.length - 1 );
			return str;
		}
        
    }
}